﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Drawing;

namespace System.Windows.Forms.ButtonInternal
{
    internal abstract partial class ButtonBaseAdapter
    {
        internal class ColorOptions
        {
            private readonly Color _backColor;
            private readonly Color _foreColor;
            private readonly IDeviceContext _deviceContext;

            public bool Enabled { get; set; }
            public bool HighContrast { get; }

            internal ColorOptions(IDeviceContext deviceContext, Color foreColor, Color backColor)
            {
                _deviceContext = deviceContext;
                _backColor = backColor;
                _foreColor = foreColor;
                HighContrast = SystemInformation.HighContrast;
            }

            internal static int Adjust255(float percentage, int value)
            {
                int result = (int)(percentage * value);
                return result > 255 ? 255 : result;
            }

            internal ColorData Calculate()
            {
                ColorData colors = new ColorData(this)
                {
                    ButtonFace = _backColor
                };

                if (_backColor == SystemColors.Control)
                {
                    colors.ButtonShadow = SystemColors.ControlDark;
                    colors.ButtonShadowDark = SystemColors.ControlDarkDark;
                    colors.Highlight = SystemColors.ControlLightLight;
                }
                else
                {
                    if (!HighContrast)
                    {
                        colors.ButtonShadow = ControlPaint.Dark(_backColor);
                        colors.ButtonShadowDark = ControlPaint.DarkDark(_backColor);
                        colors.Highlight = ControlPaint.LightLight(_backColor);
                    }
                    else
                    {
                        colors.ButtonShadow = ControlPaint.Dark(_backColor);
                        colors.ButtonShadowDark = ControlPaint.LightLight(_backColor);
                        colors.Highlight = ControlPaint.LightLight(_backColor);
                    }
                }

                colors.WindowDisabled = HighContrast ? SystemColors.GrayText : colors.ButtonShadow;

                const float lowlight = .1f;
                float adjust = 1 - lowlight;

                if (colors.ButtonFace.GetBrightness() < .5)
                {
                    adjust = 1 + lowlight * 2;
                }

                colors.LowButtonFace = Color.FromArgb(
                    Adjust255(adjust, colors.ButtonFace.R),
                    Adjust255(adjust, colors.ButtonFace.G),
                    Adjust255(adjust, colors.ButtonFace.B));

                adjust = 1 - lowlight;
                if (colors.Highlight.GetBrightness() < .5)
                {
                    adjust = 1 + lowlight * 2;
                }

                colors.LowHighlight = Color.FromArgb(
                    Adjust255(adjust, colors.Highlight.R),
                    Adjust255(adjust, colors.Highlight.G),
                    Adjust255(adjust, colors.Highlight.B));

                if (HighContrast && _backColor != SystemColors.Control)
                {
                    colors.Highlight = colors.LowHighlight;
                }

                colors.WindowFrame = _foreColor;

                if (colors.ButtonFace.GetBrightness() < .5)
                {
                    colors.ConstrastButtonShadow = colors.LowHighlight;
                }
                else
                {
                    colors.ConstrastButtonShadow = colors.ButtonShadow;
                }

                if (!Enabled)
                {
                    colors.WindowText = colors.WindowDisabled;
                    if (HighContrast)
                    {
                        colors.WindowFrame = colors.WindowDisabled;
                        colors.ButtonShadow = colors.WindowDisabled;
                    }
                }
                else
                {
                    colors.WindowText = colors.WindowFrame;
                }

                using var hdc = new DeviceContextHdcScope(_deviceContext, applyGraphicsState: false);

                colors.ButtonFace = hdc.FindNearestColor(colors.ButtonFace);
                colors.ButtonShadow = hdc.FindNearestColor(colors.ButtonShadow);
                colors.ButtonShadowDark = hdc.FindNearestColor(colors.ButtonShadowDark);
                colors.ConstrastButtonShadow = hdc.FindNearestColor(colors.ConstrastButtonShadow);
                colors.WindowText = hdc.FindNearestColor(colors.WindowText);
                colors.Highlight = hdc.FindNearestColor(colors.Highlight);
                colors.LowHighlight = hdc.FindNearestColor(colors.LowHighlight);
                colors.LowButtonFace = hdc.FindNearestColor(colors.LowButtonFace);
                colors.WindowFrame = hdc.FindNearestColor(colors.WindowFrame);
                colors.WindowDisabled = hdc.FindNearestColor(colors.WindowDisabled);

                return colors;
            }
        }
    }
}
